package utils;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.func.VoidFunc0;
import cn.hutool.core.util.StrUtil;
import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.ComThread;
import com.jacob.com.Dispatch;
import com.jacob.com.Variant;
import entity.WordType;

import java.io.File;

/**
 * jacob操作word(只能在windows系统使用)
 *
 * @author yousj
 * @since 2022/4/23
 */
public class WordUtil {

    private String docFile; // 源文件
    private ActiveXComponent word; // Word应用
    private Dispatch doc; // 打开的文档

    /**
     * 构造
     */
    public WordUtil(String docFile) {
        this.docFile = docFile;
        ComThread.InitSTA();
        word = new ActiveXComponent("Word.Application");
        word.setProperty("Visible", new Variant(false));
        doc = Dispatch.invoke(word.getProperty("Documents").toDispatch(), "Open", Dispatch.Method,
                new Object[]{docFile, new Variant(false), new Variant(true)}, new int[1]).toDispatch();
    }

    /**
     * 更新目录并另存为
     */
    public void updateCatalogue(int fmt) {
        Dispatch activeDocument = word.getProperty("ActiveDocument").toDispatch();
        Dispatch tablesOfContents = Dispatch.get(activeDocument, "TablesOfContents").toDispatch();
        // 更新目录，有两个方法：Update　更新域，UpdatePageNumbers　只更新页码
        Dispatch toc = Dispatch.call(tablesOfContents, "Item", new Variant(1)).toDispatch();
        Dispatch.call(toc, "Update");
        convertDocFmt(fmt);
    }


    /**
     * 另存为
     *
     * @param fmt 另存为文档格式
     */
    public void convertDocFmt(int fmt) {
        String targetPath = StrUtil.replace(this.docFile, "." + FileUtil.getSuffix(this.docFile), "." + WordType.getTypeByCode(fmt));
        Dispatch.invoke(doc, "SaveAs", Dispatch.Method, new Object[]{targetPath, new Variant(fmt)}, new int[1]);
        new File(targetPath);
    }


    public void call(VoidFunc0 voidFunc0) {
        try {
            voidFunc0.callWithRuntimeException();
        } finally {
            if (doc != null) {
                Dispatch.call(doc, "Close", new Variant(false));
            }
            if (word != null) {
                word.invoke("Quit", new Variant[]{});
            }
            ComThread.Release();
        }
    }

    public static void main(String[] args) {
        String docFile = "F:\\ff.doc";
        WordUtil wordUtil = new WordUtil(docFile);

        // 另存为
        // wordUtil.call(() -> wordUtil.convertDocFmt(WordType.DOCX.getCode()));

        // 更新目录然后另存为
        wordUtil.call(() -> wordUtil.updateCatalogue(WordType.DOCX.getCode()));
    }

}
